<template>
  <div>
    <p>
      <el-button type="primary" @click="openAddDialog(null)">添加一级分类</el-button>
    </p>
    <el-table :data="tableData" style="width: 90%" row-key="id" border lazy :load="load"
              :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
      <el-table-column prop="name" label="分类名称" width="240" />
      <el-table-column align="center" label="分类级别" width="190">
        <template #default="scope">
          <span>{{ getLevelText(getLevel(scope.row)) }}</span>
        </template>
      </el-table-column>
      <el-table-column align="center" label="排序号" prop="sort" width="190" />
      <el-table-column align="center" label="状态" width="180">
        <template #default="scope">
          <el-tag :type="scope.row.status === 1 ? 'success' : 'info'">
            {{ scope.row.status === 1 ? '显示' : '隐藏' }}
          </el-tag>
        </template>
      </el-table-column>

      <el-table-column align="center" label="图标" width="180">
        <template #default="scope">
          <el-image v-if="isImageUrl(scope.row.icon)" :src="scope.row.icon" fit="contain"
                    style="width: 32px; height: 32px" />
          <i v-else-if="scope.row.icon" :class="scope.row.icon" style="font-size: 20px"></i>
          <span v-else>-</span>
        </template>
      </el-table-column>

      <el-table-column align="center" label="操作" width="350">
        <template #default="scope">
          <el-dropdown trigger="click">
            <el-button size="mini" v-bind="$attrs" class="operation-button">操作
              <el-icon class="el-icon--right"><ArrowDown /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item @click="openEditDialog(scope.row)">编辑</el-dropdown-item>
                <el-dropdown-item style="color: #f56c6c;" @click="deleteCategory(scope.row)">删除</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
          <el-button
            v-if="getLevel(scope.row) < 3"
            size="mini"
            type="danger"
            @click="openAddDialog(scope.row)"
            style="margin-left: 8px;"
          >
            + 添加子分类
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>

  <!-- 新增、编辑弹框 -->
  <el-dialog :title="dialogTitle" v-model="dialogVisible">
    <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
      <el-form-item label="分类名称" prop="name">
        <el-input v-model="form.name" />
      </el-form-item>
      <el-form-item label="排序">
        <el-input-number v-model="form.sort" :max="999" :min="1" />
      </el-form-item>
      <el-form-item label="状态">
        <el-switch v-model="form.status" :active-value="1" :inactive-value="0" active-text="显示" inactive-text="隐藏" />
      </el-form-item>
      <el-form-item label="图标">
        <el-input v-model="form.icon" placeholder="请输入图标class或图片URL" />
        <div style="margin-top: 8px;">
          <el-image v-if="isImageUrl(form.icon)" :src="form.icon" fit="contain"
                    style="width: 32px;height: 32px;vertical-align: middle;" />
          <i v-else-if="form.icon" :class="form.icon" style="font-size: 20px;vertical-align: middle;"></i>
          <span v-else style="color: #ccc;">无预览</span>
        </div>
      </el-form-item>
    </el-form>
    <div footer>
      <el-button @click="dialogVisible = false">取消</el-button>
      <el-button type="primary" @click="doSave">保存</el-button>
    </div>
  </el-dialog>
</template>

<script lang="ts" setup>
import request from '@/utils/request.js'
import { onMounted, reactive, ref } from 'vue'
import { ElMessage,ElMessageBox  } from 'element-plus'
import { ArrowDown } from '@element-plus/icons-vue'

interface Category {
  id: number | null;
  name: string;
  parentId: number;
  icon: string;
  sort: number;
  status: number;
  children: Category[];
  parent?: Category | null;
  level?: number;
}

const load = (
  row: Category,
  treeNode: unknown,
  resolve: (data: Category[]) => void
) => {
  setTimeout(() => {
    resolve([
      {
        id: 31,
        name: 'wangxiaohu',
        parentId: row.id as number,
        level: row.level + 1,
        icon: '',
        sort: 0,
        status: 1,
        children: []
      },
      {
        id: 32,
        name: 'wangxiaohu',
        parentId: row.id as number,
        level: row.level + 1,
        icon: '',
        sort: 0,
        status: 1,
        children: []
      },
    ])
  }, 1000)
}
// 表格数据
const tableData: Category[] = reactive([])
// 表单引用
const formRef = ref()
// 对话框状态
const dialogVisible = ref(false)
const dialogTitle = ref('')
const currentParent = ref<Category | null>(null)
// 表单数据
const form = reactive({
  id: null,
  name: '',
  parentId: 0,
  icon: '',
  sort: 1,
  status: 1
})

// 表单验证规则
const rules = {
  name: [
    { required: true, message: '请输入分类名称', trigger: 'blur' },
    { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
  ]
}
const initDate = async () => {
  const { data } = await request.get("/api/category")
  tableData.push(...data)
  ensureChildrenArray(tableData)
  console.log(data)
}
const ensureChildrenArray = (list: Category[], parent: Category | null = null): Category[] => {
  return list.map(node => {
    if (!Array.isArray(node.children)) node.children = []
    if (node.children.length > 0) node.children = ensureChildrenArray(node.children, node);
    node.parent = parent;
    return node;
  });
};

// 检查是否为图片URL
const isImageUrl = (url: string): boolean => {
  return typeof url === 'string' && /^https?:\/\/.+\.(jpg|jpeg|png|gif|webp|svg)$/i.test(url);
};

// 获取分类级别
const getLevel = (row: Category): number => {
  let level = 1;
  let parent = row.parent;
  while (parent) {
    level++;
    parent = parent.parent;
  }
  return level;
};
// 获取级别文本
const getLevelText = (level: number): string => {
  if (level === 1) return '一级';
  if (level === 2) return '二级';
  if (level === 3) return '三级';
  return `${level}级`;
};


// 打开添加对话框
const openAddDialog = (parent: Category | null) => {
  dialogTitle.value = parent ? '添加子分类' : '添加一级分类'

  let maxSort = 0
  if (parent && parent.children && parent.children.length > 0) {
    maxSort = Math.max(...parent.children.map(item => item.sort || 0))
  } else if (!parent && tableData.length > 0) {
    maxSort = Math.max(...tableData.map(item => item.sort || 0))
  }

  // 重置表单
  Object.assign(form, {
    id: null,
    name: '',
    parentId: parent ? parent.id as number : 0,
    icon: '',
    sort: maxSort + 1,
    status: 1
  })

  currentParent.value = parent
  dialogVisible.value = true
}

// 打开编辑对话框
const openEditDialog = (row: Category) => {
  dialogTitle.value = '编辑分类'
  // 深拷贝对象，避免直接修改表格数据
  Object.assign({}, row)
  currentParent.value = null
  dialogVisible.value = true
}

// 保存分类
const doSave = async () => {
  // 验证表单
  const valid = await formRef.value.validate()
  if (!valid) return

  const { id, name, parentId, icon, sort, status } = form
  const submitForm = { id, name, parentId, icon, sort, status }

  try {
    const res = await request.post('/api/saveOrUpdate', submitForm)
    if (res.code === 0) {
      ElMessage.success('保存成功')
      dialogVisible.value = false
      // 重新加载数据
      tableData.length = 0
      initDate()
    } else {
      ElMessage.error(res.data?.msg || '保存失败')
    }
  } catch {
    ElMessage.error('保存失败，请重试')
  }
}

// 删除分类
const deleteCategory = async (row: Category) => {
  if(row.children && row.children.length>0){
    ElMessage.warning("请先删除所有子分类")
    return
  }
  try {
    await ElMessageBox.confirm(
      '此操作将永久删除该分类, 是否继续?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning', // 弹框类型，显示警告图标
      }
    );
    const data = await request.post(`/api/delete/${row.id}`)
    console.log(data.code)
    if (data.code === 0) {
      ElMessage.success('删除成功')
      console.log(data)
      // 重新加载数据
      tableData.length = 0
      initDate()
    } else {
      ElMessage.error(data.data?.msg || '删除失败')
    }
  } catch {
    ElMessage.error('删除失败，请重试')
  }
}

onMounted(() => {
  initDate()
})
</script>
